package org.intellij.plugins.junit4;

import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.roots.ModuleFileIndex;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiManager;

/**
 * @author Justin Tomich
 */
public class JavaFileBuilder
{
    private PsiManager psiManager;
    private ClassNameResolver resolver;
    private VirtualFile file;


    public JavaFileBuilder setFile(VirtualFile file)
    {
        this.file = file;
        return this;
    }


    public JavaFileBuilder setResolver(ClassNameResolver resolver)
    {
        this.resolver = resolver;
        return this;
    }


    public JavaFileBuilder setPsiManager(PsiManager psiManager)
    {
        this.psiManager = psiManager;
        return this;
    }


    public JavaFile create()
    {
        validate(); // validate makes sure it's a java file
        PsiJavaFile pjf = (PsiJavaFile) psiManager.findFile(file);
        boolean isTest = isTest(pjf);
        return new JavaFile(pjf, isTest, psiManager, resolver);
    }


    private void validate()
    {
        // not using commons lib to avoid unplesansant runtime dependencies
        notNull(psiManager, "psiManager");
        notNull(resolver, "resolver");
        notNull(file, "file");
        if (!isJavaFile())
        {
            throw new RuntimeException("Not a java file: " + file.getName());
        }
    }


    private void notNull(Object object, String name)
    {
        if (object == null) throw new RuntimeException(name + " is null");
    }


    private boolean isJavaFile()
    {
        if (file == null) return false;
        if (!file.isValid()) return false;
        if (file.isDirectory()) return false;
        PsiFile psiFile = psiManager.findFile(file);
        return psiFile instanceof PsiJavaFile;
    }


    private boolean isTest(PsiJavaFile psiJavaFile)
    {
        assert psiJavaFile != null;
        Module m = ModuleUtil.findModuleForPsiElement(psiJavaFile);
        ModuleRootManager mgr = ModuleRootManager.getInstance(m);
        ModuleFileIndex index = mgr.getFileIndex();
        VirtualFile file = psiJavaFile.getVirtualFile();
        assert file != null;
        assert file.exists();
        return index.isInTestSourceContent(file);
    }

}
